package com.power.sifa.approve.executor.impl;

import com.aventrix.jnanoid.jnanoid.NanoIdUtils;
import com.plf.common.domain.ResponseDTO;
import com.plf.common.utils.PdfConvertUtil;
import com.plf.common.utils.StringUtil;
import com.plf.common.utils.WordUtil;
import com.plf.core.base.model.Ha_attachment;
import com.plf.core.base.service.Ha_attachmentService;
import com.power.flowable.api.IPersonalFeign;
import com.power.sifa.util.executor.AbstractPostExecutor;
import com.power.sifa.approve.model.Apl_admre_audit;
import com.power.sifa.approve.model.Apl_admreview;
import com.power.sifa.approve.model.Apl_main;
import com.power.sifa.approve.model.Aprv_process_materials;
import com.power.sifa.approve.model.enumeration.*;
import com.power.sifa.approve.service.*;
import com.power.sifa.net.service.ApplyService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;
import java.util.Map;

/**
 * @author xiongzhiwen
 * @version 1.0
 * @description: 审理 变更主办人员
 * @date 2024/4/25 17:52
 */


@Component
@Slf4j
public class HearAuditChange extends AbstractPostExecutor {

    // 用户id
    private String userid;
    // 环节分类标识
    private String category;
    // 用户名
    private String username;
    // 单位id
    private String sectionid;
    // 单位名称
    private String sectionname;
    // 部门id
    private String deptid;
    // 部门名称
    private String deptname;
    // 处理意见
    private String remark;
    // 行政区划
    private String adid;
    // 环节名称
    private String taskname;

    @Resource
    private ApplyService applyService;
    @Resource
    private Apl_mainService apl_mainService;
    @Resource
    private Ha_attachmentService ha_attachmentService;
    @Resource
    private Aprv_process_materialsService aprv_process_materialsService;
    @Resource
    private Apl_admre_auditService apl_admre_auditService;
    @Resource
    private Apl_admreviewService apl_admreviewService;
    @Resource
    private BusinessApproveService businessApproveService;
    @Resource
    private IPersonalFeign iPersonalFeign;

    @Override
    public void init(Map<String, Object> initdata) {
        this.userid = (String) initdata.get("userid");
        this.category = (String) initdata.get("category");
        this.username = (String) initdata.get("username");
        this.sectionid = (String) initdata.get("sectionid");
        this.sectionname = (String) initdata.get("sectionname");
        this.deptid = (String) initdata.get("deptid");
        this.deptname = (String) initdata.get("deptname");
        this.remark = (String) initdata.get("remark");
        this.adid = (String) initdata.get("adid");
        this.taskname = (String) initdata.get("taskname");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> execute() throws Exception {
        // 1. 查询子流程的表单数据
        Apl_main mainObj = apl_mainService.getById(super.applyid);

        Apl_admre_audit auditObj = this.apl_admre_auditService.getById(super.applyid);
        {
            // 查询承办人和协办人流程变量
            ResponseDTO res = iPersonalFeign.getProcessVariable(mainObj.getInstid());
            if (0 != res.getCode()) {
                log.error("AdmreAuditChange 查询承办人和协办人流程变量失败 msg -> {}", res.getMsg());
                throw new RuntimeException("查询承办人和协办人流程变量失败");
            }
            Map<String, String> variableMap = (Map<String, String>) res.getData();
            switch (auditObj.getType()) {
                // 变更承办人
                case Tp_proctype.HEAR_CHANGE_FIRTPER: {
                    String hearfirstid = variableMap.get("hearfirstid");
                    String hearfirstname = variableMap.get("hearfirstname");
                    if (StringUtil.isEmpty(hearfirstid) || StringUtil.isEmpty(hearfirstname)) {
                        log.error("HEAR_CHANGE_FIRTPER 流程业务变量缺失 -> {}, {}", hearfirstid, hearfirstname);
                        throw new RuntimeException("流程业务变量缺失");
                    }
                    this.apl_admreviewService.updatesHearFirstUser(auditObj.getApplyid(), hearfirstid, hearfirstname);
                    Apl_main faMainObj = this.apl_mainService.getById(auditObj.getApplyid());
                    // 先激活父流程
                    ResponseDTO activeRes = this.iPersonalFeign.activationProcess(faMainObj.getInstid());
                    if (0 != activeRes.getCode()) {
                        log.error("HearAuditChange 激活父流程失败 -> msg[{}]", activeRes.getMsg());
                        throw new RuntimeException("HearAuditChange 激活父流程失败 -> " + activeRes.getMsg());
                    }
                    // 更新流程认领人员
                    ResponseDTO resClaim = this.iPersonalFeign.claimTaskByInstid(faMainObj.getInstid(), hearfirstid);
                    if (0 != resClaim.getCode()) {
                        log.error("HearAuditChange 变更承办人失败 msg -> {}", resClaim.getMsg());
                        throw new RuntimeException("变更承办人失败");
                    }
                    break;
                }
                // 变更协办人
                case Tp_proctype.HEAR_CHANGE_SECONDPER: {
                    String hearsecondid = variableMap.get("hearsecondid");
                    String hearsecondname = variableMap.get("hearsecondname");
                    if (StringUtil.isEmpty(hearsecondid) || StringUtil.isEmpty(hearsecondname)) {
                        log.error("HEAR_CHANGE_SECONDPER 流程业务变量缺失 -> {}, {}", hearsecondid, hearsecondname);
                        throw new RuntimeException("流程业务变量缺失");
                    }
                    this.apl_admreviewService.updatesHearSecondUser(auditObj.getApplyid(), hearsecondid, hearsecondname);
                    break;
                }
                default: {
                    log.error("HearAuditChange 变更办案人员业务类型错误 -> {}", auditObj.getType());
                    throw new RuntimeException("HearAuditChange 变更办案人员业务类型错误");
                }
            }
        }

        Map<String, Object> formData = this.applyService.formLoadField(mainObj.getFormid(), super.applyid);
        // 审批表意见和日期字段
        super.ApprovalField(formData);

        // 2. 生成并上传文件
        Ha_attachment attachment;
        byte[] pdfByte;
        WordUtil wordUtil = new WordUtil("AdmreAuditInside.docx");
        wordUtil.replaceTable(formData);
        try (OutputStream os = wordUtil.createWord();
             InputStream is = new ByteArrayInputStream(((ByteArrayOutputStream) os).toByteArray());) {
            pdfByte = PdfConvertUtil.word2pdfWithFont(is);
            attachment = ha_attachmentService.upload(new ByteArrayInputStream(pdfByte), "案件变更办案人员审批表.pdf");
            log.info("HearAuditChange 案件变更办案人员审批表生成并保存成功 -> {}", attachment.getId());
        } catch (Exception e) {
            log.error("HearAuditChange 案件变更办案人员审批表生成并保存失败 ->  msg[{}]", e.getMessage());
            throw new RuntimeException("AdmreAuditChange 案件变更办案人员审批表生成并保存失败 -> " + e.getMessage());
        }

        // 3. 保存审批系统文书, 只存父流程
        Aprv_process_materials docObj = new Aprv_process_materials(Tp_procmaterialEnum.ADMRE_REPORT);
        docObj.setId(auditObj.getApplyid() + NanoIdUtils.randomNanoId());
        // 通知书类型枚举
        docObj.setMattype(Tp_procmaterial.ADMRE_REPORT);
        docObj.setAttachid(attachment.getId());
        docObj.setCreateuserid(this.userid);
        docObj.setCreateuser(this.username);
        docObj.setCreatetime(new Date());
        docObj.setApplyid(auditObj.getApplyid());
        docObj.setType(auditObj.getType());
        docObj.setClassify(Tp_classify.DOCUMENT);
        docObj.setSonapplyid(auditObj.getId());
        this.aprv_process_materialsService.saveOrUpdate(docObj);

        // 3.1 更新子流程状态
        Apl_admreview admreObj = this.apl_admreviewService.getById(auditObj.getApplyid());
        String sonStatus;
        if (auditObj.getType().equals(Tp_proctype.HEAR_CHANGE_FIRTPER)) {
            sonStatus = this.businessApproveService.delSonStatus(admreObj.getSonstatus(), Tp_proctypeEnum.HEAR_CHANGE_FIRTPER.getStatus());
        } else {
            sonStatus = this.businessApproveService.delSonStatus(admreObj.getSonstatus(), Tp_proctypeEnum.HEAR_CHANGE_SECONDPER.getStatus());
        }
        this.apl_admreviewService.updatesSonStatus(admreObj.getId(), sonStatus);


        // 刷新文书日期
        this.businessApproveService.processEndedUpdatePreviewDoc(auditObj.getApplyid(), auditObj.getType(), null);
        // 文书盖章
        this.businessApproveService.templateStamp(auditObj.getApplyid(), auditObj.getType());
        return null;
    }
}
